//
//  value.c
//  knx_lib
//
//  Created by zym on 13-5-27.
//  Copyright (c) 2013年 Hinwo. All rights reserved.
//

#include <stdio.h>
#include <string.h>
#include "knx_interface.h"
/*
    SEEEEMMM MMMMMMMM
    (-1)^S * (0.01*M)*2^E
*/

static _u32 MAX_M = 0x7FF;
static _u32 MAX_E = 0xf;

// 所有的转换都基于网络传输，网络使用的是大端模式，如果和本地模式不一致需要转换

void swap2bytes(_u8 *data)
{
    _u8 tmp = data[0];
    data[0]= data[1];
    data[1]= tmp;
}

void  endion_swap(_u8 data[4])
{
    _u8 tmp = data[0];
    data[0]=data[3];
    data[3]=tmp;
    tmp = data[1];
    data[1] = data[2];
    data[2]= tmp;
}

void short_2bytes(_u8 *value, _u8 data[2])
{
    memcpy(data, value, 2);
    
    if(!isBigEndion())
    {
        swap2bytes(data);
    }
}

void bytes2_short(_u16 *value,short *svalue, _u8 data[2])
{
    _u8 swap[2];
    memcpy(swap, data, 2);
    
    if(!isBigEndion())
    {
        swap2bytes(swap);
    }
    
    if (value) {
        _u16 *us = (_u16 *)swap;
        *value = *us;
    }
    
    if(svalue)
    {
        short *s16 = (short *)swap;
        *svalue = *s16;
    }
}

void int_4bytes(_u8 *value, _u8 data[4])
{
    memcpy(data, value, 4);
    if(!isBigEndion())
    {
        endion_swap(data);
    }
}

void bytes4_int(_u32 *value,int *svalue, _u8 data[4])
{
    _u8 swap[4];
    memcpy(swap,data,4);

    if(!isBigEndion())
    {
        endion_swap(swap);
    }
    
    if (value) {
        _u32 *us = (_u32 *)swap;
        *value = *us;
    }
    
    if(svalue)
    {
        int *s16 = (int *)swap;
        *svalue = *s16;
    }
}

void float_4bytes(_u8 *value, _u8 data[4])
{
    memcpy(data, value, 4);
    if(!isBigEndion())
    {
        endion_swap(data);
    }
}

void bytes4_float(_u8 *floatValue, _u8 data[4])
{
    _u8 swap[4];
    memcpy(swap,data,4);
    
    if(!isBigEndion())
    {
        endion_swap(swap);
    }
    
    float * f = (float *)swap;
    *floatValue = *f;
}

void degree_2bytes(_int32 degree,_u8 data[2])
{
    _u32 S = 0;
    
    memset(data,0,2);
    
    if(degree<0)
    {
        S = 1;
        degree = 0 - degree;
    }
    
    _u32 E = 0;
    _u32 M = degree * 100;
    
    if(M < MAX_M)
    {
        printf("degree %d : E= 0, M...M = %x",degree,M);
    }
    else if(M/2 < MAX_M)
    {
        E = 1;
        M /= 2;
    }
    else
    {
        E = 2;
        
        while (E<MAX_E) {
            if(M/(1<<E) < MAX_M)
            {
                M /= (1<<E);
                break;
            }
            else
            {
                E ++;
            }
        }
    }
    
    //byte 1
    if(S == 1)
        data[0] |= 0x80;
    data[0] |= (_u8)(E<<3);
    data[0] |= (_u8)(M>>8);
    
    //byte 2
    data[1] = (_u8)(M&0xff);
}

/*
 SEEEEMMM MMMMMMMM
 (-1)^S * (0.01*M)*2^E
 */

void bytes_2_degree(_u8 data[2],float *degree)
{
    _u32 S = ((data[0]>>7)&0x1) ;
    
    _u32 E = (data[0]>>3) & 0x0f;
    _u32 M = ((data[0]&0x7) << 8) | data[1];
    
    // (0.01*M)*2^E

    float value = (0.01*M) * (1 << E);
    if (S == 1) {
        value = 0 - value;
    }
    
    *degree = value;
}

void bytes2_float(float value,_u8 data[2])
{
    _u32 S = 0;
    
    memset(data,0,2);
    
    if(value<0)
    {
        S = 1;
        value = 0 - value;
    }

    
}

void float_2bytes(_u8 data[2],float *degree)
{
    _u32 S = ((data[0]>>7)&0x1) ;
    
    _u32 E = (data[0]>>3) & 0x0f;
    _u32 M = ((data[0]&0x7) << 8) | data[1];
    
    // (0.01*M)*2^E
    
    float value = (0.01*M) * (1 << E);
    if (S == 1) {
        value = 0 - value;
    }
    
    *degree = value;
}

void bytes3_2_time(_u8 data[3],KNX_VALUE_TIME *time)
{
    _u8 day = data[0];
    day = (day >> 5)&0x7;
    _u8 hours = day & 0x1F;
    time->dayOfWeek = day;
    time->hour = hours;
    time->min = data[1]&0x3f ;
    time->second = data[2]&0x3f;
}

void time_2_bytes3(_u8 data[3],KNX_VALUE_TIME *time)
{
    data[0] = (time->dayOfWeek<<5) | (time->hour&0x1f);
    data[1] = 0xf3 & time->min;
    data[2] = 0x3f & time->second;
}

void bytes3_2_date(_u8 data[3],KNX_VALUE_DATE *date)
{
    date->dayOfMonth = data[0]&0x1f;
    date->month = data[1]&0xf ;
    date->years = data[2]&0x7f;
}

void date_2_bytes3(_u8 data[3],KNX_VALUE_DATE *date)
{
    data[0] = date->dayOfMonth & 0x1f;
    data[1] = date->month & 0xf;
    data[2] = date->years & 0x7f;
}




// the data from network is big endion
float bytes4_network_2_float(_u8 data[4])
{
    _u8 tmpBuf[4];
    memcpy(tmpBuf,data,4);
    
    if (isBigEndion() == 0x0) {
        endion_swap(tmpBuf);
    }
    
    float value = *((float *)tmpBuf);
    
    return value;
}

static _int32 isBig = 0xf;

_int32 isBigEndion()
{
    if (isBig == 0xf) {
        short a = 0x1122;//十六进制，一个数值占4位
        char b =  *(char *)&a;  //通过将short(2字节)强制类型转换成char单字节，b指向a的起始字节（低字节）
        if( b == 0x11)//低字节存的是数据的高字节数据
        {
            //是大端模式
            isBig = 0x1;
        }
        else
        {
            //是小端模式
            isBig = 0x0;
        }
    }
    
    return isBig;
}

_u8 onebit_parser(_u8 data[])
{
    return (data[0] & 0x1) ;
}

_u8 onebyte_parser(_u8 *data,_u8 len)
{
    return data[0] ;
}

